﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using devtm.Collections;
using devtm.Exceptions;

namespace devtm.Types.LazyLoading
{


    public class ResolveWorker : IDisposable
    {

        private ResolveAssembly o;

        public ResolveWorker(ResolveAssembly o)
        {
            this.o = o;
            o.Start();
        }

        public void Dispose()
        {
            o.Stop();
        }

    }

    public interface IGetTypes : IDisposable
    {
        IEnumerable<Type> GetTypes(Assembly assembly);
        Type GetType(string type);
        T GetObject<T>(Func<T> act);
        void ExecuteObject(Action act);
        ResolveAssembly Resolver {get; }

        stLDirectories RefreshFiles(stLDirectories dirs);
    }

    [Serializable]
    public class ClsGetTypes : IGetTypes
    {

        #region ctor / destor

        public ResolveAssembly Resolver { get; private set; }

        public ClsGetTypes()
        {
            Resolver = new ResolveAssembly();
        }

        public void Dispose()
        {
            Resolver.Stop();
        }

        #endregion


        #region Methodes

        public IEnumerable<Type> GetTypes(Assembly assembly)
        {

            using (ResolveWorker i = new ResolveWorker(this.Resolver))
            {
                foreach (Type type in assembly.GetTypes())
                    yield return type;
            }
        }


        public Type GetType(string type)
        {
            using (ResolveWorker i = new ResolveWorker(this.Resolver))
            {
                return Type.GetType(type);
            }
        }


        public T GetObject<T>(Func<T> act)
        {
            using (ResolveWorker i = new ResolveWorker(this.Resolver))
            {
                return act();
            }
        }


        public void ExecuteObject(Action act)
        {
            using (ResolveWorker i = new ResolveWorker(this.Resolver))
            {
                act();
            }
        }

        /// <summary>
        /// find all the types from the Assemblies
        /// </summary>
        /// <returns></returns>
        public stLDirectories RefreshFiles(stLDirectories dirs)
        {
            ListException listeErreur = null;

            using (ResolveWorker i = new ResolveWorker(this.Resolver))
            {

                if (dirs == null)
                    dirs = new stLDirectories(this);

                foreach (var dir in Directories)
                {
                    if (!dirs.ContainsKey(dir.FullName))
                        dirs.Add(dir);

                    try
                    {
                        dirs[dir.FullName].RefrehFile();
                    }

                    catch (BadImageFormatException)
                    {

                    }
                    catch (ListException ex1)
                    {

                        if (listeErreur == null)
                            listeErreur = ex1;
                        else
                            foreach (var e in ex1)
                                listeErreur.Add(e);

                    }
                    catch (Exception)
                    {
                        throw;
                    }

                }

            }

            if (listeErreur != null)
                throw listeErreur;

            return dirs;

        }

        #endregion

        public static TableCollection<DirectoryInfo, string> Directories { get; set; }


    }
}
